#include "app_jump.h"
#include <string.h>

/**
  * @brief  反初始化所有外设
  * @param  None
  * @retval None
  */
void APP_DeInitPeripherals(void)
{
    // 停止所有可能产生中断的外设
    HAL_RCC_DeInit();
    
    // 关闭所有使能的中断
    __disable_irq();
    
    // 重置SysTick
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;
    
    // 关闭所有外设时钟（根据需要调整）
    __HAL_RCC_GPIOA_CLK_DISABLE();
    __HAL_RCC_GPIOB_CLK_DISABLE();
    __HAL_RCC_GPIOC_CLK_DISABLE();
    __HAL_RCC_GPIOD_CLK_DISABLE();
    __HAL_RCC_GPIOE_CLK_DISABLE();
    __HAL_RCC_GPIOF_CLK_DISABLE();
    __HAL_RCC_GPIOG_CLK_DISABLE();
    
    // 禁用其他可能使用的外设时钟
    // __HAL_RCC_USART1_CLK_DISABLE();
    // __HAL_RCC_SPI1_CLK_DISABLE();
    // __HAL_RCC_I2C1_CLK_DISABLE();
    // 等等...
    
    // 清理NVIC，禁用所有中断
    for (int i = 0; i < 8; i++) {
        NVIC->ICER[i] = 0xFFFFFFFF;  // 清除使能的中断
        NVIC->ICPR[i] = 0xFFFFFFFF;  // 清除pending的中断
    }
}

/**
  * @brief  检查APP是否有效
  * @param  None
  * @retval 1-有效, 0-无效
  */
uint8_t APP_IsValidApplication(void)
{
    // 检查堆栈指针是否在合法范围内
    if ((APP_STACK_POINTER < 0x20000000) || 
        (APP_STACK_POINTER > 0x20020000)) {  // RAM范围检查
        return 0;
    }
    
    // 检查复位向量是否在FLASH范围内
    if ((APP_RESET_HANDLER < 0x08000000) || 
        (APP_RESET_HANDLER > 0x08100000)) {  // FLASH范围检查
        return 0;
    }
    
    // 检查前8个字节是否不是全0xFF（擦除状态）
    uint32_t* app_start = (uint32_t*)APP_START_ADDRESS;
    if (app_start[0] == 0xFFFFFFFF && app_start[1] == 0xFFFFFFFF) {
        return 0;
    }
    
    return 1;
}

/**
  * @brief  跳转到应用程序
  * @param  None
  * @retval None
  */
void APP_JumpToApplication(void)
{
    // 函数指针定义
    void (*app_reset_handler)(void);
    
    // 检查APP是否有效
    if (!APP_IsValidApplication()) {
        // 无效的APP，可以在这里处理错误
        // 比如跳转到bootloader或者系统复位
        NVIC_SystemReset();
        return;
    }
    
    // 反初始化所有外设
    APP_DeInitPeripherals();
    
    // 设置堆栈指针
    __set_MSP(APP_STACK_POINTER);
    
    // 设置复位处理函数地址
    app_reset_handler = (void (*)(void))APP_RESET_HANDLER;
    
    // 跳转到应用程序
    app_reset_handler();
}

/**
  * @brief  系统软件复位
  * @param  None
  * @retval None
  */
void APP_SystemReset(void)
{
    NVIC_SystemReset();
}

// 简单的跳转
void APP_SimpleJump(void)
{
    printf("Checking application validity...\r\n");
    
    if (APP_IsValidApplication()) {
        printf("Application is valid, jumping...\r\n");
        HAL_Delay(100);
        APP_JumpToApplication();
    } else {
        printf("Application is invalid!\r\n");
    }
}
